In [1]:
import sys
import os
sys.path.insert(0, os.path.abspath('../'))
sys.path.insert(0, os.path.abspath('../../'))
sys.path.insert(0, os.path.abspath('/home/hm-tlacherm/qlm_notebooks/notebooks_1.2.1/notebooks/master_thesis_qaoa/'))
sys.path.insert(0, os.path.abspath('/home/hm-tlacherm/qlm_notebooks/notebooks_1.2.1/notebooks/master_thesis_qaoa/ibm/'))
In [2]:
import numpy as np

import qiskit
provider = qiskit.IBMQ.load_account()
from qiskit import Aer
from qiskit.utils import QuantumInstance
from qiskit_optimization.algorithms import MinimumEigenOptimizer
from qiskit.algorithms import QAOA
from shared.QiskitMaxcut import *
from ibm.ibm_parameters import *

from matplotlib import pyplot as plt
%matplotlib inline
In [3]:
graph = generate_butterfly_graph(with_weights=True)
max_cut = Maxcut(graph)
max_cut_qubo = max_cut.to_qubo()
print(graph.name)
max_cut.draw()
graph_05_06_02_w
In [4]:
step_size = 0.1
a_gamma = np.arange(0, np.pi, step_size)
b_beta = np.arange(0, np.pi, step_size)
In [5]:
a_gamma, b_beta = np.meshgrid(a_gamma, b_beta)
In [6]:
quantum_instance = QuantumInstance(
                    backend=Aer.get_backend(DEFAULT_QASM_SIMULATOR),
                    shots=SHOTS)
qaoa = QAOA(
            optimizer=COBYLA(maxiter=0),
            quantum_instance=quantum_instance,
            reps=1
            )

op, offset = max_cut_qubo.to_ising()
In [7]:
def maxcut_obj(x, G):
    """
    Given a bitstring as a solution, this function returns
    the number of edges shared between the two partitions
    of the graph.
    
    Args:
        x: str
           solution bitstring
           
        G: networkx graph
        
    Returns:
        obj: float
             Objective
    """
    obj = 0
    for i,j,w in graph.edges.data('weight'):
        if x[i] != x[j]:
            obj -= w
            
    return obj


def compute_expectation(counts, G):
    
    """
    Computes expectation value based on measurement results
    
    Args:
        counts: dict
                key as bitstring, val as count
           
        G: networkx graph
        
    Returns:
        avg: float
             expectation value
    """
    
    avg = 0
    sum_count = 0
    for bitstring, count in counts.items():
        
        obj = maxcut_obj(bitstring, G)
        avg += obj * count
        sum_count += count
        
    return avg/sum_count
In [8]:
def create_cirucit(gamma,beta):
    circuits = qaoa.construct_circuit([gamma,beta], operator=op)
    circuit = circuits[0]
    circuit.measure_all()
    return circuit
In [9]:
landscape = np.zeros(a_gamma.shape)

for i in range(0, len(landscape)):
    circuits = []
    for j in range(0, len(landscape)):
        # create circuits for entire row 
        circuit = create_cirucit(a_gamma[i][j], b_beta[i][j])
        circuits.append(circuit)
    
    # create one job with circuits 
    job_name = f"{graph.name}_row_{i}"
    job = qiskit.execute(circuits, backend=provider.get_backend('ibmq_mumbai'), shots=8000)
    job.update_name(job_name)
    print(job_name)
    
    # add results to landscape 
    j = 0
    for count in job.result().get_counts():
        mean = compute_expectation(count, graph)
        landscape[i,j] = mean
        j += 1
graph_05_06_02_w_row_0
graph_05_06_02_w_row_1
graph_05_06_02_w_row_2
graph_05_06_02_w_row_3
graph_05_06_02_w_row_4
graph_05_06_02_w_row_5
graph_05_06_02_w_row_6
graph_05_06_02_w_row_7
graph_05_06_02_w_row_8
graph_05_06_02_w_row_9
graph_05_06_02_w_row_10
graph_05_06_02_w_row_11
graph_05_06_02_w_row_12
graph_05_06_02_w_row_13
graph_05_06_02_w_row_14
graph_05_06_02_w_row_15
graph_05_06_02_w_row_16
graph_05_06_02_w_row_17
graph_05_06_02_w_row_18
graph_05_06_02_w_row_19
graph_05_06_02_w_row_20
graph_05_06_02_w_row_21
graph_05_06_02_w_row_22
graph_05_06_02_w_row_23
graph_05_06_02_w_row_24
graph_05_06_02_w_row_25
graph_05_06_02_w_row_26
graph_05_06_02_w_row_27
graph_05_06_02_w_row_28
graph_05_06_02_w_row_29
graph_05_06_02_w_row_30
graph_05_06_02_w_row_31
In [10]:
print(landscape)
plt.matshow(landscape)
plt.show()
[[-23.78325  -24.142875 -23.5375   ... -24.702125 -24.77175  -24.50825 ]
 [-24.250625 -22.4275   -20.305375 ... -26.43725  -25.715125 -24.71025 ]
 [-24.175375 -23.87475  -23.49225  ... -24.128375 -24.235    -24.311875]
 ...
 [-24.65275  -24.943    -25.44075  ... -24.1045   -23.963375 -24.37475 ]
 [-24.542125 -24.28875  -24.406625 ... -25.075375 -24.8785   -24.5215  ]
 [-23.83375  -23.693375 -23.866    ... -24.219625 -24.19025  -24.028375]]
In [11]:
# Mean of landscape
np.mean(landscape)
Out[11]:
-23.71866442871094
In [12]:
# Minimium 
np.min(landscape)
Out[12]:
-28.062375
In [13]:
# Display Coordinates of Minimum 
np.unravel_index(np.argmin(landscape), landscape.shape)
Out[13]:
(19, 6)
In [14]:
# Gamma and beta value of Minimium
gamma, beta = np.unravel_index(np.argmin(landscape), landscape.shape)
opt_gamma = gamma * step_size
opt_beta = beta * step_size
print(f"Opt.Gamma: {opt_gamma}, Opt.Beta: {opt_beta}")
Opt.Gamma: 1.9000000000000001, Opt.Beta: 0.6000000000000001
In [15]:
# Save result matrix 
with open('landscape_mumbai_butterfly_weights_results.npy', 'wb') as f:
    np.save(f, landscape)
In [16]:
import plotly.graph_objects as go
In [17]:
# Plot landscape in 3D 
a_gamma = np.arange(0, np.pi, step_size)
b_beta = np.arange(0, np.pi, step_size)
fig = go.Figure(data=go.Surface(z=landscape, x=a_gamma, y=b_beta))

fig.update_traces(contours_z=dict(show=True, usecolormap=True, highlightcolor='limegreen', project_z=True))


fig.update_layout(title="QAOA MaxCut", scene=dict(
    xaxis_title="gamma",
    yaxis_title="beta",
    zaxis_title="mean"
))
In [18]:
# Plot Heatmap 
fig = go.Figure(data=go.Heatmap(z=landscape, x=b_beta, y=a_gamma, type = 'heatmap', colorscale = 'viridis'))

# Update Layout
fig.update_layout(title="QAOA MaxCut", width=700, height=700, xaxis_title="beta", yaxis_title="gamma")

# Display Global Minimium 
fig.add_trace(
    go.Scatter(mode="markers", x=[opt_beta], y=[opt_gamma], marker_symbol=[204], text = [landscape[gamma,beta]],
                   marker_color="red",  hovertemplate="x: %{x}<br>y: %{y}<br> z: %{text:.2f}<extra></extra>", 
                   marker_line_width=1, marker_size=16))
In [19]:
# Display Optimizer Results

# Display path 
#fig.add_trace(
#    go.Scatter(mode="lines", x=gammas, y=betas, marker_symbol=[200],
#                   marker_color="white", marker_line_width=1, marker_size=8)
#)

# Display start point
#fig.add_trace(
#    go.Scatter(mode="markers", x=[gammas[0]], y=[betas[0]], marker_symbol=[204],
#                   marker_color="gray", 
#                   marker_line_width=1, marker_size=16))

# Display end point
#fig.add_trace(
#    go.Scatter(mode="markers", x=[gammas[-1]], y=[betas[-1]], marker_symbol=[204],
#                   marker_color="green", 
#                   marker_line_width=1, marker_size=16))
In [20]:
# Plot Optimizer History
#fig = go.Figure(data=go.Scatter(x=counts, y=values))
#fig.update_layout(xaxis_title="Evaluation Counts", yaxis_title="Evaluated Mean", title="Optimizer")
#fig.show()
In [ ]: